package com.sea.base.widget

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.IntRange
import androidx.annotation.Px
import androidx.core.view.ViewCompat
import com.custom.widget.R
import com.sea.base.ext.global.dp
import com.sea.base.ext.global.getCurrentMillis
import kotlin.math.max

/**
 * 游戏中头像的波浪效果
 */
class GamingAvatarAnimView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
    View(context, attrs, defStyleAttr) {
    private val borderRectF = RectF()
    private val borderPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
    }
    private var animWidth = 8.dp
    private var animMillis = 1000L
    private var animIntervalMillis = 500L
    private val animRectF = RectF()
    private val animPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        style = Paint.Style.STROKE
    }

    init {
        if (attrs != null) {
            val a = context.obtainStyledAttributes(attrs, R.styleable.GamingAvatarAnimView, defStyleAttr, 0)

            setBorderWidth(a.getDimensionPixelSize(R.styleable.GamingAvatarAnimView_borderWidth, 1.dp))
            setBorderColor(a.getColor(R.styleable.GamingAvatarAnimView_borderColor, 0))
            setAnimInfo(
                a.getDimensionPixelSize(R.styleable.GamingAvatarAnimView_animWidth, animWidth),
                a.getInt(R.styleable.GamingAvatarAnimView_animMillis, animMillis.toInt()).toLong(),
                a.getInt(R.styleable.GamingAvatarAnimView_animIntervalMillis, animIntervalMillis.toInt()).toLong(),
            )

            a.recycle()
        }
    }

    private var animFirstFrameMillis = 0L
    private val intervalRun = Runnable {
        if (ViewCompat.isAttachedToWindow(this)) {
            isStart = isStart
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (borderPaint.strokeWidth > 0 && isStart) {
            canvas.drawOval(borderRectF, borderPaint)

            val now = getCurrentMillis()
            val level = now - animFirstFrameMillis
            if (level < animMillis) {
                animPaint.strokeWidth = borderPaint.strokeWidth
                val defColor = borderPaint.color and 0x00ffffff
                animPaint.color = ((0xff * (animMillis - level) / animMillis).toInt() shl 24) or defColor
                val offset = animWidth * level / animMillis
                animRectF.set(
                    borderRectF.left - offset,
                    borderRectF.top - offset,
                    borderRectF.right + offset,
                    borderRectF.bottom + offset,
                )
                canvas.drawOval(animRectF, animPaint)
                invalidate()
            } else {
                //循环动画
                removeCallbacks(intervalRun)
                postDelayed(intervalRun, animIntervalMillis - (level - animMillis))
            }
        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        if (w != oldw || h != oldh) {//init完第一次layout时也会走一遍
            newRadiusBorderPath()
        }
    }

    override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
        super.setPadding(left, top, right, bottom)
        newRadiusBorderPath()
    }

    private fun newRadiusBorderPath() {
        val stroke2 = borderPaint.strokeWidth / 2
        borderRectF.set(
            paddingStart + stroke2 - 1 + animWidth,
            paddingTop + stroke2 - 1 + animWidth,
            width - paddingEnd - stroke2 + 1 - animWidth,
            height - paddingBottom - stroke2 + 1 - animWidth
        )
    }

    var isStart = false
        set(value) {
            field = value
            removeCallbacks(intervalRun)
            animFirstFrameMillis = if (value) getCurrentMillis() else 0L
            invalidate()
        }

    /**
     * =0表示无描边
     */
    fun setBorderWidth(@Px @IntRange(from = 0) borderWidth: Int) {
        borderPaint.strokeWidth = max(0f, borderWidth.toFloat())
        newRadiusBorderPath()
        invalidate()
    }

    fun setBorderColor(@ColorInt borderColor: Int) {
        borderPaint.color = borderColor
        invalidate()
    }

    /**
     * @param animWidth 动画宽度范围，anim的宽高=头像宽高+2*animWidth
     * @param animMillis 单次动画时长
     * @param animIntervalMillis 循环动画的每次间隔
     */
    fun setAnimInfo(animWidth: Int = this.animWidth, animMillis: Long = this.animMillis, animIntervalMillis: Long) {
        this.animWidth = animWidth
        this.animMillis = animMillis
        this.animIntervalMillis = animIntervalMillis
        newRadiusBorderPath()
        isStart = isStart
    }
}